/* This class contains helpers for manipulating 802.16 messages
 * and getting the packet size.
 * This software was developed at the National Institute of Standards and
 * Technology by employees of the Federal Government in the course of
 * their official duties. Pursuant to title 17 Section 105 of the United
 * States Code this software is not subject to copyright protection and
 * is in the public domain.
 * NIST assumes no responsibility whatsoever for its use by other parties,
 * and makes no guarantees, expressed or implied, about its quality,
 * reliability, or any other characteristic.
 * <BR>
 * We would appreciate acknowledgement if the software is used.
 * <BR>
 * NIST ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
 * DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
 * FROM THE USE OF THIS SOFTWARE.
 * </PRE></P>
 * @author  rouil
 */

#include "mac802_16pkt.h"

/**
 * Return the size of the MOB_NBR-ADV frame
 * @param frame The frame
 */
int
Mac802_16pkt::getMOB_NBR_ADV_size (mac802_16_mob_nbr_adv_frame * frame)
{
    int size = 4;			//min size
    if ((frame->skip_opt_field & 0x1) == 0)
        size += 3;			//add operator id

    for (int i = 0; i < frame->n_neighbors; i++)
    {
        size += 4;		//min size for neighbor info
        if (frame->nbr_info[i].phy_profile_id.FAindex & 0x1)
            size++;
        if (frame->nbr_info[i].phy_profile_id.bs_eirp & 0x1)
            size++;
        if ((frame->skip_opt_field & 0x2) == 0)
            size += 3;		//contain neighbor bs id
        if ((frame->skip_opt_field & 0x4) == 0)
            size++;			//contain HO process optimization
        if ((frame->skip_opt_field & 0x8) == 0)
            size++;			//contain neighbor bs id
        if (frame->nbr_info[i].dcd_included)
            size += 2 + GET_DCD_SIZE (frame->nbr_info[i].dcd_settings.nb_prof);
        if (frame->nbr_info[i].ucd_included)
            size += 2 + GET_UCD_SIZE (frame->nbr_info[i].ucd_settings.nb_prof);
        if (frame->nbr_info[i].phy_included)
            size += 2;
    }

    return size;
}

/**
 * Return the size of the MOB_SCN-REQ
 * @param frame The frame
 */
int
Mac802_16pkt::getMOB_SCN_REQ_size (mac802_16_mob_scn_req_frame * frame)
{
    int size = 6;

    if (frame->n_recommended_bs_index != 0)
        size++;
    int tmp =
        11 * (frame->n_recommended_bs_index + frame->n_recommended_bs_full);
    size += tmp / 8;
    if ((tmp % 8) != 0)
        size++;

    return size;
}

/**
 * Return the size of the MOB_SCN-RSP
 * @param frame The frame
 */
int
Mac802_16pkt::getMOB_SCN_RSP_size (mac802_16_mob_scn_rsp_frame * frame)
{
    int size = 6;

    if (frame->scan_duration != 0)
    {
        size += 3;
        if (frame->n_recommended_bs_index != 0)
            size++;
        int tmp = 0;
        for (int i = 0; i < frame->n_recommended_bs_index; i++)
        {
            tmp += 11;
            if (frame->rec_bs_index[i].scanning_type == 2 ||
                    frame->rec_bs_index[i].scanning_type == 3)
                tmp += 24;
        }
        for (int i = 0; i < frame->n_recommended_bs_index; i++)
        {
            tmp += 51;
            if (frame->rec_bs_index[i].scanning_type == 2 ||
                    frame->rec_bs_index[i].scanning_type == 3)
                tmp += 24;
        }
        size += tmp / 8;
        if ((tmp % 8) != 0)
            size++;
    }

    return size;
}

/**
 * Return the size of the MOB_MSHO-REQ
 * @param frame The frame
 */
int
Mac802_16pkt::getMOB_MSHO_REQ_size (mac802_16_mob_msho_req_frame * frame)
{
    int size = 4;
    int tmp, tmpB;

    tmp = 0;
    tmpB = 0;

    if (frame->n_new_bs_index != 0)
        size++;

    if (frame->report_metric & 0x1)
        tmp++;
    if (frame->report_metric & 0x2)
        tmp++;
    if (frame->report_metric & 0x4)
        tmp++;

    for (int i = 0; i < frame->n_new_bs_index; i++)
    {
        tmpB += 20 + 8 * tmp;
        if (frame->bs_index[i].arrival_time_diff_ind & 0x1)
            tmpB += 4;
    }
    //n_new_bs_full
    for (int i = 0; i < frame->n_new_bs_full; i++)
    {
        tmpB += 20 + 8 * tmp;
        if (frame->bs_full[i].arrival_time_diff_ind & 0x1)
            tmpB += 4;
    }
    tmpB += 4;
    //N_current
    if (frame->report_metric & 0x8)
        tmp++;
    for (int i = 0; i < frame->n_current_bs; i++)
    {
        tmpB += 4 + 8 * tmp;
    }
    //increase size
    size += tmp / 8;
    if ((tmp % 8) != 0)
        size++;			//includes padding

    return size;
}

/**
 * Return the size of the MOB_MSHO-REQ
 * @param frame The frame
 */
int
Mac802_16pkt::getMOB_BSHO_RSP_size (mac802_16_mob_bsho_rsp_frame * frame)
{
    int size = 4;

    return size;
}

/**
 * Return the size of the MOB_HO-IND
 * @param frame The frame
 */
int
Mac802_16pkt::getMOB_HO_IND_size (mac802_16_mob_ho_ind_frame * frame)
{
    int size = 4;

    return size;
}
